import {Component, OnInit} from '@angular/core';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import {NzMessageService} from 'ng-zorro-antd/message';

import {MenuService} from './menu.service';
import {PermissionService} from '../../../service/permission.service';
import {Global} from '../../../shared/global';
import {HomeService} from '../../home/home.service';

@Component({
  selector: 'app-menu',
  templateUrl: './menu.component.html',
  styleUrls: ['./menu.component.scss']
})
export class MenuComponent implements OnInit {

  /**
   * 模态框表单
   */
  modalForm!: FormGroup;
  /**
   * tab表格数据
   */
  listOfData?: any | null = [];
  /**
   * 模态框显示 or 隐藏
   */
  isVisible = false;
  parentDisabled = false;
  treeSelectOptions?: any = [];
  tableData = [];
  mapOfExpandedData: { [key: string]: any[] } = {};
  typeAvailable = new Set(['1', '2', '3']); // 控制菜单类型可选项
  // 菜单模块列表
  menuList: any;
  // 当前选中模块
  module: any;

  constructor(
    private message: NzMessageService,
    private fb: FormBuilder,
    private menuService: MenuService,
    public permission: PermissionService,
    public homeService: HomeService
  ) {
  }

  collapse(array: any[], data: any, $event: boolean): void {
    if (!$event) {
      if (data.children) {
        data.children.forEach((d: { key: any; }) => {
          // tslint:disable-next-line:no-non-null-assertion
          const target = array.find(a => a.key === d.key)!;
          target.expand = false;
          this.collapse(array, target, false);
        });
      } else {
        return;
      }
    }
  }

  convertTreeToList(root: TreeNodeInterface): TreeNodeInterface[] {
    const stack: TreeNodeInterface[] = [];
    const array: TreeNodeInterface[] = [];
    const hashMap = {};
    stack.push({...root, level: 0, expand: false});

    while (stack.length !== 0) {
      const node = stack.pop()!;
      this.visitNode(node, hashMap, array);
      if (node.children) {
        for (let i = node.children.length - 1; i >= 0; i--) {
          stack.push({...node.children[i], level: node.level! + 1, expand: false, parent: node});
        }
      }
    }

    return array;
  }

  visitNode(node: TreeNodeInterface, hashMap: { [key: string]: boolean }, array: TreeNodeInterface[]): void {
    if (!hashMap[node.key]) {
      hashMap[node.key] = true;
      array.push(node);
    }
  }

  ngOnInit(): void {
    this.modalForm = this.fb.group({
      id: [null],
      // 父Id
      cId: [null],
      // 菜单名称
      name: [null, [Validators.required]],
      // 图标
      icon: [null],
      // 请求地址
      path: [null],
      // 权限标识
      keyword: [null, [Validators.required]],
      // 显示排序
      sort: [0, [Validators.required]],
      // 状态
      isHide: ['1'],
      // 类型 1：目录 2:菜单 3:按钮
      type: ['1'],
      // 备注
      remarks: [null],
    });
    this.homeService.menuList().subscribe(res => {
      if (res.code === 0) {
        this.menuList = res.data.sys;
        // @ts-ignore
        this.module = this.menuList[0].id;
        this.list();
      }
    });
  }

  /**
   * 打开模态框 初始化
   */
  showModal(data?: any, isAdd = true): void {
    this.isVisible = true;
    this.typeAvailable = new Set(['1', '2', '3']);
    if (!isAdd && data.id != null) {
      this.typeAvailable = new Set([`${data.type}`]);
      this.modalForm.get('id')?.setValue(data.id);
      this.parentDisabled = true;
      this.details(data.id);
    }
  }

  addChildren(data: any) {
    this.isVisible = true;
    this.parentDisabled = true;
    switch (data.type * 1) {
      case 1:
        this.typeAvailable = new Set(['2', '3']);
        this.modalForm.get('type')?.setValue('2');
        break;
      case 2:
        this.typeAvailable = new Set(['3']);
        this.modalForm.get('type')?.setValue('3');
        break;
      case 3:
        this.typeAvailable = new Set(['3']);
        this.modalForm.get('type')?.setValue('3');
        break;
    }
    this.modalForm.get('cId')?.setValue(data.id);
  }

  /**
   * 模态框关闭触发
   */
  handleCancel(): void {
    this.isVisible = false;
    this.parentDisabled = false;
    this.modalForm.reset();
    this.typeAvailable = new Set(['1', '2', '3']);
    this.modalForm.get('id')?.setValue('');
    this.modalForm.get('isHide')?.setValue('1');
    this.modalForm.get('type')?.setValue('1');
  }

  /**
   * 新增 or 编辑 模态框提交
   */
  submitForm(): void {
    for (const i in this.modalForm.controls) {
      if (this.modalForm.controls.hasOwnProperty(i)) {
        this.modalForm.controls[i].markAsDirty();
        this.modalForm.controls[i].updateValueAndValidity();
      }
    }
    if (this.modalForm.status !== 'VALID') {
      return;
    }
    this.modalForm.value.cId = this.modalForm.value.cId || '0';
    if (this.modalForm.value.id) {
      this.menuService.update({...this.modalForm.value, sysId: this.module}).subscribe((res: any) => {
        if (res.code !== 0) {
          this.createMessage('error', res.message);
          return;
        }
        this.createMessage('success', '菜单保存成功');
        this.handleCancel();
        this.list();
      }, err => {
      });
    } else {
      this.menuService.addMenu({...this.modalForm.value, sysId: this.module}).subscribe((res: any) => {
        if (res.code !== 0) {
          this.createMessage('error', res.message);
          return;
        }
        this.createMessage('success', '菜单添加成功');
        this.handleCancel();
        this.list();
      }, err => {
      });
    }
  }

  /**
   * 确认是否删除
   * @params id
   */
  deleteMenu(id: string) {
    this.menuService.delete({id}).subscribe((res: any) => {
      if (res.code !== 0) {
        this.createMessage('error', res.message);
        return;
      }
      this.createMessage('success', '菜单删除成功');
      this.list();
    }, err => {
    });
  }

  /**
   * 查询菜单列表
   */
  list() {
    this.menuService.list({sysId: this.module}).subscribe((res: any) => {
      this.treeSelectOptions = JSON.parse(JSON.stringify(res.data));
      this.formatTreeSelectOptions(this.treeSelectOptions);
      this.tableData = res.data;
      this.renameIdToKey(this.tableData);

      this.tableData.forEach((item: any) => {
        this.mapOfExpandedData[item.key] = this.convertTreeToList(item);
      });
      this.forChildren(this.listOfData);
    }, err => {
    });
  }

  // 格式化模态框树选择数据
  formatTreeSelectOptions(list: any) {
    list.forEach((item: any) => {
      item.title = item.name;
      item.key = item.id;
      delete item.name;
      delete item.id;
      item.isLeaf = !item.children?.length;
      if (item.children?.length) {
        this.formatTreeSelectOptions(item.children);
      }
    });
  }

  // 添加属性 key
  renameIdToKey(list: any) {
    list.forEach((item: any) => {
      item.key = item.id;
      if (item.children?.length) {
        this.renameIdToKey(item.children);
      } else {
        delete item.children;
      }
    });
  }

  forChildren(children: any) {
    children.forEach((item: any) => {
      if (item.children && item.children.length > 0) {
        item.expanded = true;
        this.forChildren(item.children);
      } else {
        item.isLeaf = true;
      }
    });
  }

  /**
   * 角色详情
   */
  details(id: any) {
    this.menuService.details(id).subscribe((res: any) => {
      if (res.code !== 0) {
        this.createMessage('error', res.message);
        return;
      }
      const tabData = res.data;

      // tslint:disable:no-non-null-assertion
      this.modalForm.get('id')!.setValue(tabData.id);
      this.modalForm.get('cId')!.setValue(tabData.cid);
      this.modalForm.get('name')!.setValue(tabData.name);
      this.modalForm.get('icon')!.setValue(tabData.icon);
      this.modalForm.get('path')!.setValue(tabData.path);
      this.modalForm.get('keyword')!.setValue(tabData.keyword);
      this.modalForm.get('sort')!.setValue(tabData.sort);
      this.modalForm.get('isHide')!.setValue(tabData.isHide + '');
      this.modalForm.get('remarks')!.setValue(tabData.remarks);
      this.modalForm.get('type')!.setValue(tabData.type + '');
    }, err => {
    });
  }

  /**
   * 全局展示操作反馈信息
   * @param type 其他提示类型 success:成功 error:失败 warning:警告
   */
  createMessage(type: any, str: any): void {
    this.message.create(type, str);
  }

  moduleChange() {
    console.log(this.module);
    this.list();
  }
}

export interface TreeNodeInterface {
  key: string;
  name: string;
  isHide?: number;
  keyword?: string;
  icon?: string;
  path?: string;
  remark?: string;
  sort?: number;
  type?: number;
  level?: number;
  expand?: boolean;
  children?: TreeNodeInterface[];
  parent?: TreeNodeInterface;
}
